﻿using System;
using System.Net;
using System.Runtime.Serialization;
using System.Collections.Generic;




namespace BusinessApplication1.ServiceReference
{

    public partial class Project
    {

        public enum PriorityValues { High /* Высокий*/, Medium /* Средний*/, Low /* Низкий*/};

        #region Конструкторы
        // Конструктор без ProjectID
        public Project()
        {
            Name = "Проект № 1";
            Description = "Тестовй проект";
        }

        public Project(string _name, string _description, DateTime _plannedStartExecution, DateTime _plannedFinishExecution, string _projectPriority,
            TimeSpan _recoverTime)
        {
            string nullString = "Нет данных";

            Name = (String.IsNullOrEmpty(_name)) ? nullString : _name;

            Description = (String.IsNullOrEmpty(_description)) ? nullString : _description;



            PlanFinishDateTime = (_plannedFinishExecution == null) ? DateTime.Now : _plannedFinishExecution;

            PlanStartDateTime = (_plannedStartExecution == null) ? DateTime.Now : _plannedStartExecution;

            Priority = _projectPriority;
        }

        #endregion

        


    }

    public partial class Task
    {
        public Task()
        {

            var ths = new TaskHasStatu();
            ths.Status = new Status();
            ths.Status.IDStatus = (decimal) TaskProjectStatuses.notAssigned;
            if (this.TaskHasStatus != null)
            this.TaskHasStatus.Add(ths);
            //MainPage.statusChanged += new StatusChangedEventHandler(task_statusChanged);
        }




        public int x;
        // Конструктор без TaskID




        public void setTaskStatus(TaskProjectStatuses mainStat)
        {
            var ths = new TaskHasStatu();
            ths.Status = new Status();
            ths.Status.IDStatus = (decimal)mainStat;
        }
    }

    public partial class SystemUser
    {
        public static List<ReportsTo> userReportsToTree = new List<ReportsTo>(); // дерово иерархии между пользователями
        public static List<Execute> userTaskList = new List<Execute>(); // список задач всех пользователей
        public static List<Role> allRolesList = new List<Role>(); // список всех ролей в БД

        //    public decimal IDUser;
        //    public string Name; // имя
        //    public string Surname; //фамилия
        //    public string Patronymic; // отчество
        //    public decimal IDPosition; //должность
        //    public decimal IDDuty; // обязательства
        //    public string WorkPhone; //телефон
        //    public string MobilePhone; // мобилка
        //    public string E_mail; // Рабочая почта
        //    public string E_mail2; //Домашняя почта
        //    public string Login;
        //    public string Password_Hash_;
        //    public string ProfileStatus; // актив/неактив

        //пустой конструктор
        public SystemUser() { }

        // полный конструктор - с UserID, когда выгружаем информацию из БД
        public SystemUser(decimal _userID, string _name, string _surname, string _patronymic, decimal _positionID, decimal _dutyID,
                    string _workPhone, string _mobilePhone, string _e_mail, string _e_mail2, string _login, string _password_Hash_,
                    bool _profileStatus)
        {
            IDUser = _userID;
            Name = _name;
            Surname = _surname;
            Patronymic = _patronymic;
            IDPosition = _positionID;
            IDDuty = _dutyID;
            WorkPhone = _workPhone;
            MobilePhone = _mobilePhone;
            E_mail = _e_mail;
            E_mail2 = _e_mail2;
            Login = _login;
            Password_Hash_ = _password_Hash_;
            if (_profileStatus) ProfileStatus = "Active";
            else ProfileStatus = "InActive";
        }

        // типовой конструктор - без UserID -  он нам неизвестен
        public SystemUser(string _name, string _surname, string _patronymic, decimal _positionID, decimal _dutyID,
                    string _workPhone, string _mobilePhone, string _e_mail, string _e_mail2, string _login)
        {
            Name = _name;
            Surname = _surname;
            Patronymic = _patronymic;
            IDPosition = _positionID;
            IDDuty = _dutyID;
            WorkPhone = _workPhone;
            MobilePhone = _mobilePhone;
            E_mail = _e_mail;
            E_mail2 = _e_mail2;
            Login = _login;
            Password_Hash_ = generatePassword();
            ProfileStatus = "Active";

            sendLogPass();
        }

        //~SystemUser() { }

        private string generatePassword() // заглушка генератора пароля (принцип генерации нуждается в разработке)
        { return "12345"; }

        private void sendLogPass() // заглушка. будет отсылать логин/пароль на мыло когда начнём прогать сетевую часть (возможно этот метод здесь и не нужен и будет написан в интерфейсной части)
        { }

        public static SystemUser getUserFromDB(decimal _UserId) //получает данные юзера из БД по его ID. Без взаимодействия с БД не сделать.
        {
            SystemUser gUser = new SystemUser();
            // далее идёт извлечение и формирование полей на основе данных из БД
            return gUser;
        }

        public static void addUserToDB(SystemUser newUser, List<decimal> rolesList) // добавление юзера в БД
        {
           // ProjectManagement.ServiceReference.AddUser(newUser);
        }

        public static void changeUserInDB(SystemUser changeUser, List<decimal> rolesList) // изменение юзера в БД (присваивание параметров передаваемого юзеру в БД с тем же ИДом).
        {
        }
        public static void changeUserInDB(SystemUser changeUser) // тоже самое без изменения ролей пользователей
        {
        }

        public static void removeUserFromDB(decimal _UserID) // удаление юзера из БД. без взаимодейств с БД не сделать.
        {
        }

        public static void loadUserTreeFromDB() 
        { 
        }

        public static void loadUserTreeFromDB(int userIerarchyLevel) 
        { 
        }

        public static void saveUserTreeToDB() // сохраняет измененную структуру связей в БД
        {
        }

        public static List<decimal> getUserRolesFromDB(decimal _UserID)
        {
            List<decimal> tempRolesList = new List<decimal>();
            // далее идет загрузка из БД
            return tempRolesList;
        }

        // аутентификация пользователя. Возвращает объект типа User.
        // Если логин и пароль верны и юзер активен, возвращает соответствующего юзера (с ИД > 0), по нему можно узнать всю инфу и роли
        // Если нет такого логина, возвращает пустого юзера с UserID = -1
        // Если юзер есть, но пароль неверен, возвращает пустого юзера с UserID = -2
        // Если юзер есть и пароль верен, но юзер деактивирован, возвращает пустого юзера с UserID = -3
        // Дальнейшие действия в зависимости от результата выполняются в функции кнопки ОК окна интерфейса

        public static SystemUser authenticateUser(string _login, string _password)
        {
            loadUserTreeFromDB();
            bool userFound = false;
            SystemUser usr = new SystemUser();
            SystemUser tempUser = new SystemUser();
            foreach (ReportsTo usRel in userReportsToTree)
            {
                tempUser = getUserFromDB(usRel.IDUser);
                if (tempUser.Login == _login)
                {
                    userFound = true;
                    if (tempUser.Password_Hash_ == _password)
                    {
                        if (tempUser.ProfileStatus == "Active") usr = tempUser;
                        else usr.IDUser = -3;
                    }
                    else usr.IDUser = -2;
                }
            }
            if (!userFound) usr.IDUser = -1;
            return usr;
        }

        //  восстановление пароля доступа. Генерирует новый пароль и возвращает true если юзер с указанным логином существует , иначе false
        public static bool restorePassword(string _login)
        {
            loadUserTreeFromDB();
            bool userFound = false;
            SystemUser tempUser = new SystemUser();
            foreach (ReportsTo usRel in userReportsToTree)
            {
                tempUser = getUserFromDB(usRel.IDUser);
                if (tempUser.Login == _login)
                {
                    userFound = true;
                    tempUser.Password_Hash_ = tempUser.generatePassword();
                    changeUserInDB(tempUser);
                    tempUser.sendLogPass();
                }
            }
            return userFound;
        }

        // функция выхода из системы целиком делается с помощью интерфейса, т.к. ничего передавать и получать не надо.

        public static bool checkLogin(String log, decimal _userID) // проверяет логин на уникальность, возвращает true если уникален (нет такого же у юзера с другим ID). этот метод нужно вызывать в контексте кнопки ОК. Если проверка пройдена - сохранять, а если нет - выводить предупреждение.
        {
            SystemUser tempUser = new SystemUser();
            foreach (ReportsTo usRel in userReportsToTree)
            {
                tempUser = getUserFromDB(usRel.IDUser);
                if ((tempUser.Login == log) && (tempUser.IDUser != _userID)) return false;
            }
            return true;
        }

        // проверка пароля на валидность. пока пустая, нужно придумать критерии для паролей
        // вызывается из интерфейса перед собственно сменой паролей. Смена паролей вызывается если проверка пройдена
        static bool checkPassword(string _password)
        { return true; }

        // Установка нового пароля.. Возвращает false если старый пароль не верен, иначе меняет на новый и возвращает true
        public static bool setNewPassword(decimal _userID, String oldpassword, String newpassword) // меняет пароль на новый
        {
            SystemUser usr = getUserFromDB(_userID);
            if (usr.Password_Hash_ == oldpassword)
            {
                usr.Password_Hash_ = newpassword;
                changeUserInDB(usr);
                return true;
            }
            else { return false; }
        }

        public static void deactivateUser(decimal _UserID) // делают юзера неактивным
        {
            SystemUser usr = getUserFromDB(_UserID);
            usr.ProfileStatus = "InActive";
            changeUserInDB(usr);
            applyRelationChanges();
        }

        public void activateUser(decimal _UserID) // делает юзера активным
        {
            SystemUser usr = getUserFromDB(_UserID);
            usr.ProfileStatus = "Active";
            changeUserInDB(usr);
            applyRelationChanges();
        }

        public static List<decimal> getSubordersList(decimal userID) // получает список подчинённых пользователя с данным идентификатором
        {
            List<decimal> tempSubordersList = new List<decimal>();
            foreach (ReportsTo usRep in userReportsToTree) if (usRep.IDUserTo == userID) tempSubordersList.Add(usRep.IDUser);
            return tempSubordersList;
        }

        public static void addNewUser() // добавляем нового пользователя если всё ОК
        {
            // закоментированные строки надо поместить в интерфейс при инициализации окна, т.к. чтоб рисовать
            // связи надо создать объект UserRelation

            //UserRelation nURelation = new UserRelation();
            // userReportsToTree.Add(nURelation);

            string _name = "";
            string _surname = "";
            string _patronymic = "";
            decimal _positionID = 0;
            decimal _dutyID = 0;
            string _workPhone = "";
            string _mobilePhone = "";
            string _e_mail = "";
            string _e_mail2 = "";
            string _login = "";
            List<decimal> _userRoleIDs = new List<decimal>();

            // здесь должны присваиваться значения строк из интерфейса. возможно часть этого метода надо встроить в сам интерфейс а названия строк заменить на те что там используются
            SystemUser nUser = new SystemUser(_name, _surname, _patronymic, _positionID, _dutyID, _workPhone, _mobilePhone, _e_mail, _e_mail2, _login);
            foreach (ReportsTo usRel in userReportsToTree) if (usRel.IDUser == -1) usRel.IDUser = nUser.IDUser;
            addUserToDB(nUser, _userRoleIDs);
            applyRelationChanges();
        }

        public static void editUser(SystemUser usr) // метод сохраняет внесённые изменения в профиль пользователя. Срабатывает при подтверждении сохранения редактирования
        {
            string _name = "";
            string _surname = "";
            string _patronymic = "";
            decimal _positionID = 0;
            decimal _dutyID = 0;
            string _workPhone = "";
            string _mobilePhone = "";
            string _e_mail = "";
            string _e_mail2 = "";
            string _login = "";
            List<decimal> _userRoleIDs = new List<decimal>();

            // здесь должны присваиваться значения строк из интерфейса. Получение и вызов функции из БД будет в теле функции интерфейса
            usr.Name = _name;
            usr.Surname = _surname;
            usr.Patronymic = _patronymic;
            usr.IDPosition = _positionID;
            usr.IDDuty = _dutyID;
            usr.WorkPhone = _workPhone;
            usr.MobilePhone = _mobilePhone;
            usr.E_mail = _e_mail;
            usr.E_mail2 = _e_mail2;
            usr.Login = _login;
            changeUserInDB(usr, _userRoleIDs);
            applyRelationChanges();
        }

        public static void removeUser(int _userID) // удаляет юзера из временного дерева. Срабатывает при подтверждении удаления.
        {
            foreach (ReportsTo usr in userReportsToTree)
                if (usr.IDUserTo == _userID) usr.removeHead(_userID);
            removeUserFromDB(_userID);
            applyRelationChanges();
        }

        public static void applyRelationChanges() // применяет изменения в иерарх. структуре основного дерева на основе временного.
        {
            //userTree = new List<UserRelation>();
            //foreach (UserRelation usRel in userReportsToTree) userTree.Add(usRel);

            //В этом методе будешь сразу работать с userReportsToTree, не с userTree!
            saveUserTreeToDB();
        }

        public static void cancelRelationChanges() // откатывает изменения в структуре дерева. Будет применяться при нажатии отмены в интерфейсе
        {
            userReportsToTree.Clear();
        }

        public static void sendReport(decimal _taskID, string report) { } // будет отправлять отчет супервайзеру. просмотр реализуется через интерфейс. где хранить отчет хз (возможно через почту)

        // получает название роли из списка
        public static string getRoleNameByID(decimal roleID)
        {
            foreach (Role tempRole in allRolesList) if (tempRole.IDRole == roleID) return tempRole.Name;
            return "";
        }
    }


    public partial class ReportsTo // элемент иерархического дерева
    {
        //   public decimal IDUser; // идентификатор пользователя
        //   public decimal IDUserTo; // идентификатор начальника

        public ReportsTo()
        {
            IDUser = -1; // временный идентификатор нового не созданного юзера
            IDUserTo = 0;
        }
        public ReportsTo(decimal ID)
        {
            IDUser = ID;
            IDUserTo = 0;
        }

        ~ReportsTo() { SystemUser.userReportsToTree.Remove(this); }

        public void changeHead(decimal hID) // меняет начальника
        {
            IDUserTo = hID;
        }

        public void removeHead(decimal hID) // меняет подчиненного
        {
            IDUserTo = 0;
        }
        public static ReportsTo getUserReport(decimal _UserID) // получает связь по идентификатору
        {
            foreach (ReportsTo usRel in SystemUser.userReportsToTree) if (usRel.IDUser == _UserID) return usRel;
            return null;
        }

        public decimal level() // уровень иерархии
        {
            if (IDUserTo == 0) return 0;
            else return getUserReport(IDUserTo).level();
        }
    }


    public partial class Execute // элемент дерева связи юзеров с задачами
    {
        public Execute()
        {
            IDUser = 0;
            IDTask = 0;
        }
        public Execute(decimal UserID, decimal TaskID)
        {
            IDUser = UserID;
            IDTask = TaskID;
        }

        public static List<decimal> getUserTasks(decimal _UserID) // возвращает список идентификаторов задач пользователя
        {
            List<decimal> tempTaskIDList = new List<decimal>();
            foreach (Execute usEx in SystemUser.userTaskList) if (usEx.IDUser == _UserID) tempTaskIDList.Add(usEx.IDTask);
            return tempTaskIDList;
        }

        public static void AddTaskToUser(decimal _TaskID, decimal _UserID) // добавляет задачу в список задач пользователя
        {
            foreach (Execute usEx in SystemUser.userTaskList) if (usEx.IDTask == _TaskID) SystemUser.userTaskList.Remove(usEx);
            SystemUser.userTaskList.Add(new Execute(_UserID, _TaskID));
        }

        public static void RemoveTaskFromUsers(decimal _TaskID) // удаляет задачу из списка активных
        {
            foreach (Execute usEx in SystemUser.userTaskList) if (usEx.IDTask == _TaskID) SystemUser.userTaskList.Remove(usEx);
        }

    }

    public partial class Role
    {
        //   public decimal IDRole;
        //   public string Name;

        public Role(decimal roleID, string roleName)
        {
            IDRole = roleID;
            Name = roleName;
        }
    }

}
